package asteroids;

import be.kuleuven.cs.som.annotate.*;

/**
 * This class represents a bullet of the arcade game Asteroids.
 * 
 * @invar	| isValidSource(getSource())
 * 
 * @author 	Antoine Lammens & Yannick Laevaert
 * @version 2.0
 *
 */
public class Bullet extends SpaceEntity {
	
	/**
	 * Final variable registering the source of the bullet.
	 */
	private final Ship source;
	
	/**
	 * Constant reflecting the mass density of a bullet expressed in kilograms per cubic kilometre.
	 */
	private static final double BULLET_MASS_DENSITY = 7.8 * Math.pow(10,12);
	
	/**
	 * Constant reflecting the velocity of a bullet expressed in kilometres per second.
	 * 
	 * @return	| result = 250
	 */
	public static final double BULLET_VELOCITY = 250.0;
	
	/**
	 * Constant reflecting the radius of a bullet expressed in kilometres.
	 * 
	 * @return	| result = 3
	 */
	public static final double BULLET_RADIUS = 3.0;
	
	/**
	 * Variable registering the number of bounces with a boundary.
	 */
	private int nbOfBounces;
	
	/**
	 * Initialize this new bullet with given values.
	 * 
	 * @param 	xPosition
	 * 			The x-position for this new bullet.
	 * @param 	yPosition
	 * 			The y-position for this new bullet.
	 * @param 	xVelocity
	 * 			The x-velocity for this new bullet.
	 * @param 	yVelocity
	 * 			The y-velocity for this new bullet.
	 * @param	source
	 * 			The source of this new bullet.
	 * @param	world
	 * 			The world of this new bullet.
	 * @pre		| isValidSource(source)
	 * @effect	| super(xPosition, yPosition, xVelocity, yVelocity, 4/3 * Math.PI * Math.pow(BULLET_RADIUS,3) * BULLET_MASS_DENSITY, 
	 *			| 			BULLET_RADIUS, world)
	 * @post	| new.getSource() == source
	 * @post	| new.getNbOfBounces() == 0			
	 */
	public Bullet(double xPosition, double yPosition, double xVelocity, double yVelocity, Ship source, World world) {
		super(xPosition, yPosition, xVelocity, yVelocity, 4/3 * Math.PI * Math.pow(BULLET_RADIUS,3) * BULLET_MASS_DENSITY, 
				BULLET_RADIUS, world);
		assert isValidSource(source);
		this.source = source;
		this.nbOfBounces = 0;
	}
	
	/**
	 * Return the source of the bullet.
	 */
	@Basic @Immutable
	public Ship getSource() {
		return source;
	}
	
	/**
	 * Check whether the given source is a valid source.
	 * 
	 * @param 	source
	 * 			The source to check.
	 * @return 	| result == (source != null) && this.getWorld() == source.getWorld()
	 */
	public boolean isValidSource(Ship source) {
		return (source != null) && this.getWorld() == source.getWorld();
	}
	
	/**
	 * Return the number of bounces.
	 */
	@Basic
	public int getNbOfBounces() {
		return nbOfBounces;
	}
	
	/**
	 * Increment the number of bounces.
	 * 
	 * @post	| new.getNbOfBounces() == getNbOfBounces + 1
	 */
	public void incrementNbOfBounces() {
		nbOfBounces++;
	}
	
	/**
	 * Override the method bounce in SpaceEntity. This method ensures that a bullet bounces only once.
	 * 
	 * @post	| if(getNbOfBounces() < 1)
	 * 			|	then super.bounce() && incrementNbOfBounces()
	 * 			|	else terminate()
	 */
	public void bounce() {
		if (getNbOfBounces() < 1) {
			super.bounce();
			incrementNbOfBounces();
		}		
		else {
			this.terminate();
		}
	}
	
	/**
	 * Terminate this space entity.
	 * 
	 * @post	The current bullet is deleted from the list of bullets of its source.
	 * 			| new.getSource().getBullets().contains(this) == false
	 * @effect	The terminate method of the superclass SpaceEntity is invoked.
	 * 			| super.terminate()
	 */
	@Override
	public void terminate() {
		this.getSource().removeBullet(this);
		super.terminate();
	}
	
}
